/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.jfonia.connect5.intervals;

import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Set;
import org.jfonia.connect5.basics.ValueNode;
import org.jfonia.connect5.basics.Node;
import org.jfonia.connect5.basics.Observer;

/**
 *
 * @author jannes
 */
public class ObservableLinkedLongIntervalList extends LinkedLongIntervalList implements Observer{

    //this class warns his observers if element is added or removed.
    //when the child intervals themself are observable he will also warn his own observers when a child is changed
        Set<ListObserver> observers = new LinkedHashSet<ListObserver>();
        HashMap<ValueNode,Interval> endToIntervalMap = new HashMap<ValueNode, Interval>();
        
	public void addObserver(ListObserver o)
	{
		if (!observers.contains(o))
			observers.add(o);
	}

	public boolean containsObserver(ListObserver o)
	{
		return observers.contains(o);
	}

	public void removeObserver(ListObserver o)
	{
		observers.remove(o);
	}	

    @Override
    public Interval<Long> add(Interval<Long> ts)
    {
        Interval<Long> val = super.insert(size(),ts);        
        val.getEndNode().addObserver(this);
        endToIntervalMap.put(val.getEndNode(), val);
        for(ListObserver observer : observers){
            observer.intervalAdded(val);
        }
        return val;
    }

    @Override
    public Interval<Long> insert(int pos, Interval<Long> val)
    {
            Interval<Long> interval = super.insert(pos,val);            
            val.getEndNode().addObserver(this);
            endToIntervalMap.put(val.getEndNode(), val);
            for(ListObserver observer : observers){
                observer.intervalAdded(val);
            }
            return interval;
    }

    @Override
    public Interval<Long> remove(int i)
    {
            Interval<Long> interval = super.remove(i);
            endToIntervalMap.remove(interval.getEndNode());
            interval.getEndNode().removeObserver(this);
            if(interval instanceof Node){
                ((Node)interval).addObserver(this);
            }
            for(ListObserver observer : observers){
                observer.intervalRemoved(interval,i);
            }
            return interval;
    }

    public void onNotify(Object source) {
        Interval interval = endToIntervalMap.get((ValueNode)source);
        if(interval != null){
            for(ListObserver observer : observers){
                observer.intervalEndChanged(interval);
            }
        }
    }
}
